#include "cfg_file.h"

cfg_file* cfg_file::_inst = NULL;


cfg_file* cfg_file::instance()
{
	if(_inst == NULL)
		_inst = new cfg_file;
	return _inst;
}

void cfg_file::set_file(const char* file)
{
	if(_file)
		free(_file);

	if(file == NULL)
		_file = NULL;

	_file = strdup(file);
}

const char* cfg_file::get_file()
{
	return _file;
}

char* cfg_file::get(const char* key)
{
	FILE	*fp;
	char	*p;

	if(_file == NULL)
		return NULL;

	fp = fopen(_file, "r+");
	if(fp == NULL)
		return NULL;

	while(!feof(fp))
	{
		if(fgets(_buf, MAX_LINE_BUF, fp))
		{
			if(_buf[0] == '#')
				continue;

			p = strchr(_buf, '\n');
			if(p == NULL)
			{
				fclose(fp);
				return NULL;
			}
			*p = '\0';

			p = strchr(_buf, '=');
			if(p == NULL)
				continue;
			*p++ = '\0';

			if(strcmp(key, trim(_buf)) == 0)
			{
				fclose(fp);
				return trim(p);
			}
		}
	}
	fclose(fp);

	return NULL;
}

bool cfg_file::set(const char* key, const char* val)
{
	FILE	*fp, *fpo;
	char	*p, *pfile;
	long	pos;
	bool	bset;

	if(_file == NULL)
		return false;

	fp = fopen(_file, "r+");
	if(fp == NULL)
		return false;

	pfile = (char*)malloc(strlen(_file) + 5);
	if(pfile == NULL)
	{
		fclose(fp);
		return false;
	}
	strcpy(pfile, _file);
	strcat(pfile, ".tmp");

	fpo = fopen(pfile, "w");
	if(fpo == NULL)
	{
		free(pfile);
		fclose(fp);
		return false;
	}

	bset = false;

	while(!feof(fp))
	{
		if(fgets(_buf, MAX_LINE_BUF, fp))
		{
			pos = ftell(fpo);
			fputs(_buf, fpo);

			if(!bset)
			{
				if(_buf[0] == '#')
					continue;

				p = strchr(_buf, '\n');
				if(p == NULL)
				{
					fclose(fp);
					fclose(fpo);
					remove(pfile);
					return false;
				}
				*p = '\0';

				p = strchr(_buf, '=');
				if(p == NULL)
					continue;
				*p++ = '\0';

				if(strcmp(key, trim(_buf)) == 0)
				{
					bset = true;
					fseek(fpo, pos, SEEK_SET);
					fprintf(fpo, "%s = %s\n", key, val);
				}
			}
		}
	}

	if(! bset)
	{
		fprintf(fpo, "%s = %s\n", key, val);
	}

	// close files
	fclose(fp);
	pos = ftell(fpo);
	fclose(fpo);
	truncate(pfile, pos);

	// replace cfg_file file
	remove(_file);
	rename(pfile, _file);

	return true;
}

int cfg_file::get_int(const char* key, int fault_val)
{
	char* pval = get(key);
	if(pval)
	{
		return atoi(pval);
	}
	else
		return fault_val;
}

float cfg_file::get_float(const char* key, float fault_val)
{
	char* pval = get(key);
	if(pval)
	{
		return atof(pval);
	}
	else
		return fault_val;
}

bool cfg_file::set_int(const char* key, int val)
{
	char	buf[16];
	sprintf(buf, "%d", val);
	return set(key, buf);
}

bool cfg_file::set_float(const char* key, float val)
{
	char	buf[16];
	sprintf(buf, "%f", val);
	return set(key, buf);
}

cfg_file::~cfg_file()
{
	if(_file)
	{
		free(_file);
	}
}

cfg_file::cfg_file()
{
	_file = NULL;
}

char* cfg_file::trim(char* s)
{
	return rtrim(ltrim(s));
}

char* cfg_file::ltrim(char* s)
{
	if(s == NULL)
		return NULL;

	while((*s == ' ') || (*s == '\t'))
		s++;

	return s;
}

char* cfg_file::rtrim(char* s)
{
	char* p;

	if(s == NULL)
		return NULL;

	p = s;
	while(*p)
		p++;

	p--;
	while((*p == ' ') || (*p == '\t'))
		p--;
	*(p + 1) = '\0';

	return s;
}

